import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { AccessEntity } from "src/entity/access.entity";
import { RoleAccessEntity } from "src/entity/role_access.entity";
import { PageEnum } from "src/enums/status.enum";
import { CreateAccessDto } from "src/modules/background/access/dto/access.create.dto";
import { AccessReqDto } from "src/modules/background/access/dto/access.req.dto";
import { UpdateAccessDto } from "src/modules/background/access/dto/access.update.dto";
import { AccessListVo, AccessVo } from "src/modules/background/access/vo/access.vo";
import { getConnection, Repository } from "typeorm";

@Injectable()
export class AccessService {
    constructor(
        @InjectRepository(AccessEntity)
        private readonly accessRepository: Repository<AccessEntity>,
        @InjectRepository(RoleAccessEntity)
        private readonly roleAccessRepository: Repository<RoleAccessEntity>,
    ) { }

    async createAccess(createAccessDto: CreateAccessDto): Promise<string> {
        const { title, name } = createAccessDto;
        if (title) {
            const result: Pick<AccessEntity, 'id'> | undefined = await this.accessRepository.findOne({where: { title },select: ['id']});
            if (result) {
                throw new HttpException(`${title}当前菜单名称已经存在,不能重复创建`, HttpStatus.OK);
            }
        }
        if (name) {
            const result: Pick<AccessEntity, 'id'> | undefined = await this.accessRepository.findOne({
                where: { name },
                select: ['id'],
            });
            if (result) {
                throw new HttpException(`${name}当前路由name已经存在,不能重复创建`, HttpStatus.OK);
            }
        }
        const access = this.accessRepository.create(createAccessDto);
        await this.accessRepository.save(access);
        return '创建成功';
    }

    async destroyAccessById(id: number): Promise<string> {
        // 1.判断是否有角色关联到当前资源
        const roleAccessResult: Pick<RoleAccessEntity, 'id'> | undefined =
            await this.roleAccessRepository.findOne({
                where: { accessId: id },
                select: ['id'],
            });
        if (roleAccessResult) {
            throw new HttpException('当前资源已经被角色绑定不能直接删除', HttpStatus.OK);
        }
        // 2.查看该节点下是否有子节点
        const childNode: Pick<AccessEntity, 'id'> | undefined = await this.accessRepository.findOne({
            where: { parentId: id },
            select: ['id'],
        });
        if (childNode) {
            throw new HttpException('当前节点下含子节点,不能直接删除', HttpStatus.OK);
        }
        const {
            raw: { affectedRows },
        } = await this.accessRepository.softDelete(id);
        if (affectedRows) {
            return '删除成功';
        } else {
            return '删除失败';
        }
    }

    async modifyAccessById(id: number, updateAccessDto: UpdateAccessDto): Promise<string> {
        if (id <= 8) {
            throw new HttpException('系统默认生成的资源不能修改', HttpStatus.OK);
        }
        const {
            raw: { affectedRows },
        } = await this.accessRepository.update(id, updateAccessDto);
        if (affectedRows) {
            return '修改成功';
        } else {
            return '修改失败';
        }
    }
    async accessList(): Promise<AccessVo[]> {
        return await this.accessRepository.find()
    }

    async accessListPage(accessReqDto: AccessReqDto): Promise<AccessListVo> {
        const {
            pageSize = PageEnum.PAGE_SIZE,
            pageNum = PageEnum.PAGE_NUMBER,
            parentId = 0,
        } = accessReqDto;
        const [data, total] = await getConnection()
            .createQueryBuilder(AccessEntity, 'access')
            .where('access.parentId = :parentId', { parentId })
            .skip((pageNum - 1) * pageSize)
            .take(pageSize)
            .orderBy({ 'access.sortId': 'ASC', 'access.createdAt': 'DESC' })
            .printSql()
            .getManyAndCount();
        return {
            data,
            total,
            pageNum,
            pageSize,
        };
    }
}
